package com.jiemeng.sensordatawritesample;

import static android.os.Environment.DIRECTORY_DOWNLOADS;

import android.os.Environment;
import android.util.Log;

import androidx.annotation.NonNull;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;

import io.reactivex.rxjava3.core.Observer;
import io.reactivex.rxjava3.disposables.CompositeDisposable;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import io.reactivex.rxjava3.subjects.PublishSubject;

public class SensorDataRecorder {
    public static final int SENSOR_TYPE_1 = 1;
    public static final int SENSOR_TYPE_2 = 2;

    public static class SensorData {
        public SensorData(int type, String data) {
            this.type = type;
            this.data = data;
        }

        public int getType() {
            return type;
        }

        public String getData() {
            return data;
        }

        private final int type;
        private final String data;
    }

    private volatile static SensorDataRecorder sensorDataRecorder;

    private static final String TAG = "SensorDataRecorder";
    private final PublishSubject<SensorData> subject = PublishSubject.create();
    private final CompositeDisposable compositeDisposable = new CompositeDisposable();

    private final File parentPath = Environment.getExternalStoragePublicDirectory(DIRECTORY_DOWNLOADS);

    private PrintWriter recordWriter1 = null;
    private PrintWriter recordWriter2 = null;

    private SensorDataRecorder() {
    }

    public static SensorDataRecorder getInstance() {
        if (sensorDataRecorder == null) {
            synchronized (SensorDataRecorder.class) {
                if (sensorDataRecorder == null) {
                    sensorDataRecorder = new SensorDataRecorder();
                }
            }
        }
        return sensorDataRecorder;
    }

    public void init() {
        initRecordFile();
        initConsumer();
    }

    private PrintWriter createPrinterWriter(String dirname, String filename) {
        String dirPath = parentPath.getAbsolutePath() + "/" + dirname;
        try {
            File dirFile = new File(dirPath);
            if (!dirFile.exists()) {
                dirFile.mkdir();
            }

            return new PrintWriter(dirPath + "/" + filename, "UTF-8");
        } catch (IOException e) {
            Log.e(TAG, e.getMessage());
            return null;
        }
    }

    private void initRecordFile() {
        recordWriter1 = createPrinterWriter("record", "record1.text");
        recordWriter2 = createPrinterWriter("record", "record2.text");
    }

    private void initConsumer() {
        subject.subscribeOn(Schedulers.io())
                .observeOn(Schedulers.io())
                .subscribe(new Observer<SensorData>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {
                        compositeDisposable.add(d);
                    }

                    @Override
                    public void onNext(@NonNull SensorData s) {
                        switch (s.type) {
                            case SENSOR_TYPE_1:
                                recordWriter1.println(s.data);
                                break;
                            case SENSOR_TYPE_2:
                                recordWriter2.println(s.data);
                                break;
                            default:
                                break;
                        }
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {
                        Log.e(TAG, e.getMessage());
                    }

                    @Override
                    public void onComplete() {
                    }
                });
    }

    public void publishData(SensorData data) {
        subject.onNext(data);
    }

    public void dispose() {
        subject.onComplete();
        disposeFile();
        compositeDisposable.clear();
    }

    private void disposeFile() {
        if (recordWriter1 != null) {
            recordWriter1.close();
            recordWriter1 = null;
        }

        if (recordWriter2 != null) {
            recordWriter2.close();
            recordWriter2 = null;
        }
    }
}
